﻿using System;
using System.IO;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using Microsoft.SharePoint;
using Microsoft.SharePoint.Taxonomy;
using BulkCVSImporter;

namespace BulkCSVImporter
{
    public partial class Form1 : Form
    {
        #region Properties
        MetaStoreHolder _selectedMetaStore = null;
        #endregion

        #region Methods

        #endregion



        public Form1()
        {
            InitializeComponent();
            backgroundWorkerCVS.WorkerReportsProgress = true;
        }

        private void button1_Click(object sender, EventArgs e)
        {
            folderBrowserDialog1.ShowDialog();

            txbOutFolder.Text = folderBrowserDialog1.SelectedPath;
        }

        private void reportMessageBoxError(string message)
        {
            MessageBox.Show(message);
        }

        private void btnImport_Click(object sender, EventArgs e)
        {

            if (string.IsNullOrEmpty(txbSiteUrl.Text))
            {
                reportMessageBoxError("Site Url is Empty");
                txbSiteUrl.Focus();
                return;
            }


            if (string.IsNullOrEmpty(txbGroup.Text))
            {
                reportMessageBoxError("Group Name is Empty");
                txbGroup.Focus();
                return;
            }

            if (Directory.Exists(txbOutFolder.Text))
            {

                var files = from file in Directory.GetFiles(txbOutFolder.Text, "*.csv") select file;

                int count = files.Count();

                if (count == 0)
                {
                    reportMessageBoxError("No CSV files found in Directory");
                }
                else
                {
                    progressBar1.Maximum = count;
                    backgroundWorkerCVS.RunWorkerAsync();
                }
            }
            else
            {
                reportMessageBoxError("Directory Doesnt Exist");
                txbOutFolder.Focus();
            }
        }

        bool m_allTermsAdded;

        private void backgroundWorkerImporter_DoWork(object sender, DoWorkEventArgs e)
        {
            backgroundWorkerCVS.ReportProgress(0, "Connecting to Term Store");

            string socialDataStatsSite = txbSiteUrl.Text;
            TermStore _termStore = null;
            TaxonomySession _session = null;

            //Obtain current site
            using (SPSite siteColl = new SPSite(socialDataStatsSite))
            {
                //Get The context object that encapsulates all information required to make a call to a service application.
                SPServiceContext serviceContext = SPServiceContext.GetContext(siteColl);

                //The entry point to accessing all data associated with TermStore objects and performing searches across them.
                _session = new TaxonomySession(siteColl);

                if (_selectedMetaStore != null)
                {
                    _termStore = _session.TermStores[_selectedMetaStore.Guid];
                }
                else
                {
                    if (_session.TermStores.Count > 1)
                    {
                        MessageBox.Show("Multiple Metadata Services found." + Environment.NewLine + "Please select one in 'Options' first");
                        return;
                    }
                    else
                    {
                        //Represents a "term store" default database.
                        _termStore = _session.DefaultKeywordsTermStore;
                    }
                }
            }

            backgroundWorkerCVS.ReportProgress(0, "Creating/Cleaning Term Store Group");

            //Get TermStore Groups
            GroupCollection groups = _termStore.Groups;

            //Find group that we want to Import to
            Group thisGroup = groups.Where(g => g.Name == txbGroup.Text).SingleOrDefault();

            //Check that group exist
            if (thisGroup != null)
            {
                //Get all termset from that group
                TermSetCollection termSets = thisGroup.TermSets;

                //For each termset, delete it
                foreach (TermSet set in termSets)
                    set.Delete();

                //save all changes to TermStore
                _termStore.CommitAll();
            }
            //If group doesn't exist, create it
            else
            {
                thisGroup = _termStore.CreateGroup(txbGroup.Text);
                _termStore.CommitAll();
            }

            //Get all .csv files from provided folder
            var files = from file in Directory.GetFiles(txbOutFolder.Text, "*.csv") select file;
            //Get count on importing .cvs
            int count = files.Count();
            int loopcount = 0;
            StreamReader reader = null;
            string errorMessage = string.Empty;

            backgroundWorkerCVS.ReportProgress(0, "Importing *.CSV");

            //Go through each .cvs file and import it
            foreach (string filePath in files)
            {
                //Open .cvs for reading
                FileStream fileStream = new FileStream(filePath, FileMode.Open, FileAccess.Read);
                //Get .cvs file info
                FileInfo fileInfo = new FileInfo(filePath);
                backgroundWorkerCVS.ReportProgress(loopcount, "Importing : " + fileInfo.Name);

                try
                {
                    //Get Import Manager
                    ImportManager manager = thisGroup.TermStore.GetImportManager();
                    reader = new StreamReader(fileStream);
                    manager.ImportTermSet(thisGroup, reader, out m_allTermsAdded, out errorMessage);
                }
                catch
                {

                }
                finally
                {
                    if (reader != null)
                    {
                        reader.Close();
                    }
                }

                loopcount++;
                backgroundWorkerCVS.ReportProgress(loopcount, "Importerted : " + fileInfo.Name);
            }
        }

        private void backgroundWorkerImporter_ProgressChanged(object sender, ProgressChangedEventArgs e)
        {
            progressBar1.Value = e.ProgressPercentage;

            if (e.UserState != null)
                lblProgress.Text = e.UserState.ToString();
        }

        private void backgroundWorkerImporter_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
        {
            lblProgress.Text = "Done Importing *.CSV";
        }

        private void button2_Click(object sender, EventArgs e)
        {
            folderBrowserDialog1.ShowDialog();
            txbOutputPath.Text = folderBrowserDialog1.SelectedPath;
        }

        private void btnExport_Click(object sender, EventArgs e)
        {
            //Check Url text box 
            if (string.IsNullOrEmpty(txbServerUrl.Text))
            {
                reportMessageBoxError("Site Url is Empty");
                txbServerUrl.Focus();
                return;
            }

            //Check Terms Store Group text box
            if (string.IsNullOrEmpty(txbGroupName.Text))
            {
                reportMessageBoxError("Group Name is Empty");
                txbGroupName.Focus();
                return;
            }

            if (Directory.Exists(txbOutputPath.Text))
            {
                int count = GetTaxonomyHandle();

                if (count == -1)
                {
                    reportMessageBoxError("Couldn't Find Group : " + txbGroupName.Text);
                }
                //hit, when multiple stores found
                else if (count == -2)
                {
                    reportMessageBoxError("Multiple Metadata Services found." + Environment.NewLine + "Please select one in options first");
                }
                else if (count == 0)
                {
                    reportMessageBoxError("No TermSets in Group : " + txbGroupName.Text);
                }
                else
                {
                    pbExport.Maximum = count;
                    backgroundWorkerExporter.RunWorkerAsync();
                }
            }
            else
            {
                reportMessageBoxError("Directory Doesn't Exist");
                txbOutputPath.Focus();
            }
        }

        private int GetTaxonomyHandle()
        {
            string socialDataStatsSite = txbServerUrl.Text;
            TaxonomySession _session = null;

            try
            {
                //Obtain current site
                using (SPSite siteColl = new SPSite(socialDataStatsSite))
                {
                    //Get The context object that encapsulates all information required to make a call to a service application.
                    SPServiceContext serviceContext = SPServiceContext.GetContext(siteColl);

                    //The entry point to accessing all data associated with TermStore objects and performing searches across them.
                    _session = new TaxonomySession(siteColl);

                    //Get TermSets count
                    if (_selectedMetaStore != null)
                    {
                        return _session.TermStores[_selectedMetaStore.Guid].Groups[txbGroupName.Text].TermSets.Count();
                    }
                    else
                    {
                        if (_session.TermStores.Count > 1)
                        {
                            return -2;
                        }
                        else
                        {
                            return _session.DefaultKeywordsTermStore.Groups[txbGroupName.Text].TermSets.Count();
                        }
                    }
                }
            }
            catch (Exception)
            {
                return -1;
            }
        }

        private void ExportTerm(StringBuilder exportData, Term term, string heritage)
        {
            heritage = String.Concat(heritage, ",", String.Format("\"{0}\"", term.Name));
            exportData.AppendLine(String.Format(",,,{0},\"{1}\",{2}", term.IsAvailableForTagging, term.GetDescription(), heritage));
            foreach (var subTerm in term.Terms) ExportTerm(exportData, subTerm, heritage);
        }

        public void ExportTermSet(string GroupName, SPSite site)
        {
            backgroundWorkerExporter.ReportProgress(0, "Creating/Cleaning Term Store Group");

            TaxonomySession _taxonomySession = new TaxonomySession(site);
            TermStore _termStore = null;

            //Get Term Store selected by user
            if (_selectedMetaStore != null)
            {
                _termStore = _taxonomySession.TermStores[_selectedMetaStore.Guid];
            }
            else
            {
                if (_taxonomySession.TermStores.Count > 1)
                {
                    MessageBox.Show("Multiple Metadata Services found." + Environment.NewLine + "Please select one in options first");
                    return;
                }
                else
                {
                    //Represents a "term store" default database.
                    _termStore = _taxonomySession.DefaultKeywordsTermStore;
                }
            }

            //Get group specified by user
            Group group = _termStore.Groups[GroupName];

            int loop = group.TermSets.Count();
            int count = 1;

            backgroundWorkerExporter.ReportProgress(0, "Exporting *.CSV");

            foreach (TermSet oneTermSet in group.TermSets)
            {
                StringBuilder exportData = new StringBuilder();
                exportData.AppendLine("\"Term Set Name\",\"Term Set Description\",\"LCID\",\"Available for Tagging\",\"Term Description\",\"Level 1 Term\",\"Level 2 Term\",\"Level 3 Term\",\"Level 4 Term\",\"Level 5 Term\",\"Level 6 Term\",\"Level 7 Term\"");

                backgroundWorkerExporter.ReportProgress(count, "Exporting : " + oneTermSet.Name);

                foreach (var topTerm in oneTermSet.Terms)
                {
                    exportData.AppendLine(String.Format("\"{0}\",\"{1}\",,{2},\"{3}\",\"{4}\",,,,,,,", oneTermSet.Name, oneTermSet.Description, oneTermSet.IsAvailableForTagging, topTerm.GetDescription(), topTerm.Name));

                    foreach (var childTerm in topTerm.Terms) ExportTerm(exportData, childTerm, String.Format("\"{0}\"", topTerm.Name));
                }

                using (StreamWriter outfile = new StreamWriter(txbOutputPath.Text + @"\" + oneTermSet.Name + ".csv"))
                {
                    backgroundWorkerExporter.ReportProgress(count, "Writing to File : " + oneTermSet.Name + ".csv");
                    outfile.Write(exportData);
                }

                backgroundWorkerExporter.ReportProgress(count, "Exported : " + oneTermSet.Name);

                count++;
            }
        }

        private void backgroundWorkerExporter_DoWork(object sender, DoWorkEventArgs e)
        {
            string socialDataStatsSite = txbServerUrl.Text;
            ExportTermSet(txbGroupName.Text, new SPSite(socialDataStatsSite));
        }

        private void backgroundWorkerExporter_ProgressChanged(object sender, ProgressChangedEventArgs e)
        {
            pbExport.Value = e.ProgressPercentage;

            if (e.UserState != null)
                lblExport.Text = e.UserState.ToString();
        }

        private void backgroundWorkerExporter_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
        {
            lblExport.Text = "Done Exporting ";
        }

        //Opens a new windows, to collect feedback from multiple meta stores selector
        private void selectManagedStoreToolStripMenuItem_Click(object sender, EventArgs e)
        {
            string siteUrl = tabControl1.SelectedIndex == 0 ? txbSiteUrl.Text : txbServerUrl.Text;
            if (string.IsNullOrEmpty(siteUrl))
            {
                MessageBox.Show("You need to set 'SharePoint Site Url' field first.");
            }
            else
            {
                MMS storeForm = new MMS();
                storeForm.StoreUrl = siteUrl;
                storeForm.ShowDialog(this);

                if (storeForm.DialogResult == System.Windows.Forms.DialogResult.OK)
                {
                    _selectedMetaStore = (MetaStoreHolder)storeForm.ManagedStore;
                }
            }
        }

        private void aboutToolStripMenuItem_Click(object sender, EventArgs e)
        {
            AboutWindow aboutForm = new AboutWindow();
            aboutForm.ShowDialog();
        }
    }
}
